﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SharpSoft.WPF.Controls
{
    /// <summary> 
    /// 分页控件
    /// </summary>
    public class Pagination : Control
    {
        static Pagination()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(Pagination), new FrameworkPropertyMetadata(typeof(Pagination)));
        }
        public Pagination()
        {
            AddHandler(Hyperlink.ClickEvent, new RoutedEventHandler(this.LinkClick));
        }

        private void LinkClick(object sender, RoutedEventArgs e)
        {
            if (e.OriginalSource is Hyperlink hl)
            {
                if (hl.Tag is int index)
                {
                    this.CurrentPage = index;
                }
                else if (hl.Tag is string cmd)
                {
                    switch (cmd)
                    {
                        case "NEXT":
                            if (this.CurrentPage < this.PageCount)
                            {
                                this.CurrentPage++;
                            }
                            break;
                        case "PREVIOUS":
                            if (this.CurrentPage > 1)
                            {
                                this.CurrentPage--;
                            }
                            break;
                        case "FIRST":
                            this.CurrentPage = 1;
                            break;
                        case "LAST":
                            this.CurrentPage = this.PageCount;
                            break;
                        default:
                            break;
                    }
                }
            }
        }

        /// <summary>
        /// 最大可见的页面数量
        /// </summary>
        public int MaxVisiblePagesCount
        {
            get { return (int)GetValue(MaxVisiblePagesCountProperty); }
            set { SetValue(MaxVisiblePagesCountProperty, value); }
        }

        public static readonly DependencyProperty MaxVisiblePagesCountProperty =
            DependencyProperty.Register("MaxVisiblePagesCount", typeof(int), typeof(Pagination), new PropertyMetadata(5));
        /// <summary>
        /// 下一页的标题
        /// </summary>
        public object NextPageTitleContent
        {
            get { return (object)GetValue(NextPageTitleContentProperty); }
            set { SetValue(NextPageTitleContentProperty, value); }
        }

        public static readonly DependencyProperty NextPageTitleContentProperty =
            DependencyProperty.Register("NextPageTitleContent", typeof(object), typeof(Pagination), new PropertyMetadata("下一页"));


        /// <summary>
        /// 上一页的标题
        /// </summary>
        public object PreviousPageTitleContent
        {
            get { return (object)GetValue(PreviousPageTitleContentProperty); }
            set { SetValue(PreviousPageTitleContentProperty, value); }
        }

        public static readonly DependencyProperty PreviousPageTitleContentProperty =
            DependencyProperty.Register("PreviousPageTitleContent", typeof(object), typeof(Pagination), new PropertyMetadata("上一页"));

        /// <summary>
        /// 首页按钮标题
        /// </summary>
        public object FirstPageTitleContent
        {
            get { return (object)GetValue(FirstPageTitleContentProperty); }
            set { SetValue(FirstPageTitleContentProperty, value); }
        }

        public static readonly DependencyProperty FirstPageTitleContentProperty =
            DependencyProperty.Register("FirstPageTitleContent", typeof(object), typeof(Pagination), new PropertyMetadata("首页"));
        /// <summary>
        /// 尾页按钮标题
        /// </summary>
        public object LastPageTitleContent
        {
            get { return (object)GetValue(LastPageTitleContentProperty); }
            set { SetValue(LastPageTitleContentProperty, value); }
        }

        public static readonly DependencyProperty LastPageTitleContentProperty =
            DependencyProperty.Register("LastPageTitleContent", typeof(object), typeof(Pagination), new PropertyMetadata("尾页"));




        /// <summary>
        /// “转到”功能的界面是否显示
        /// </summary>
        public bool GotoPageUIVisible
        {
            get { return (bool)GetValue(GotoPageUIVisibleProperty); }
            set { SetValue(GotoPageUIVisibleProperty, value); }
        }

        public static readonly DependencyProperty GotoPageUIVisibleProperty =
            DependencyProperty.Register("GotoPageUIVisible", typeof(bool), typeof(Pagination), new PropertyMetadata(true));
        /// <summary>
        /// “转到”功能按钮的标题
        /// </summary>
        public object GotoPageUITitleContent
        {
            get { return (object)GetValue(GotoPageUITitleContentProperty); }
            set { SetValue(GotoPageUITitleContentProperty, value); }
        }

        public static readonly DependencyProperty GotoPageUITitleContentProperty =
            DependencyProperty.Register("GotoPageUITitleContent", typeof(object), typeof(Pagination), new PropertyMetadata("转到"));

        /// <summary>
        /// 页面数量
        /// </summary>
        public int PageCount
        {
            get { return (int)GetValue(PageCountProperty); }
            set { SetValue(PageCountProperty, value); }
        }

        public static readonly DependencyProperty PageCountProperty =
            DependencyProperty.Register("PageCount", typeof(int), typeof(Pagination), new PropertyMetadata(default(int)));
        /// <summary>
        /// 当前页索引，从1开始
        /// </summary>
        public int CurrentPage
        {
            get { return (int)GetValue(CurrentPageProperty); }
            set { SetValue(CurrentPageProperty, value); }
        }

        public static readonly DependencyProperty CurrentPageProperty =
            DependencyProperty.Register("CurrentPage", typeof(int), typeof(Pagination), new PropertyMetadata(0));


        public bool CanNext
        {
            get { return (bool)GetValue(CanNextProperty); }
            private set { SetValue(CanNextPropertyKey, value); }
        }
        private static DependencyPropertyKey CanNextPropertyKey = DependencyProperty.RegisterReadOnly("CanNext", typeof(bool), typeof(Pagination), new PropertyMetadata(default(bool)));
        public static DependencyProperty CanNextProperty = CanNextPropertyKey.DependencyProperty;

        public bool CanPrevious
        {
            get { return (bool)GetValue(CanPreviousProperty); }
            private set { SetValue(CanPreviousPropertyKey, value); }
        }
        private static DependencyPropertyKey CanPreviousPropertyKey = DependencyProperty.RegisterReadOnly("CanPrevious", typeof(bool), typeof(Pagination), new PropertyMetadata(default(bool)));
        public static DependencyProperty CanPreviousProperty = CanPreviousPropertyKey.DependencyProperty;


        public bool CanFirst
        {
            get { return (bool)GetValue(CanFirstProperty); }
            private set { SetValue(CanFirstPropertyKey, value); }
        }
        private static DependencyPropertyKey CanFirstPropertyKey = DependencyProperty.RegisterReadOnly("CanFirst", typeof(bool), typeof(Pagination), new PropertyMetadata(default(bool)));
        public static DependencyProperty CanFirstProperty = CanFirstPropertyKey.DependencyProperty;


        public bool CanLast
        {
            get { return (bool)GetValue(CanLastProperty); }
            set { SetValue(CanLastProperty, value); }
        }

        public static readonly DependencyProperty CanLastProperty =
            DependencyProperty.Register("CanLast", typeof(bool), typeof(Pagination), new PropertyMetadata(default(bool)));
        /// <summary>
        /// 左边是否有需要隐藏的页面
        /// </summary>
        public bool LeftHasMorePage
        {
            get { return (bool)GetValue(LeftHasMorePageProperty); }
            private set { SetValue(LeftHasMorePagePropertyKey, value); }
        }
        private static DependencyPropertyKey LeftHasMorePagePropertyKey = DependencyProperty.RegisterReadOnly("LeftHasMorePage", typeof(bool), typeof(Pagination), new PropertyMetadata(default(bool)));
        public static DependencyProperty LeftHasMorePageProperty = LeftHasMorePagePropertyKey.DependencyProperty;
        /// <summary>
        /// 右边是否有需要隐藏的页面
        /// </summary>
        public bool RightHasMorePage
        {
            get { return (bool)GetValue(RightHasMorePageProperty); }
            private set { SetValue(RightHasMorePagePropertyKey, value); }
        }
        private static DependencyPropertyKey RightHasMorePagePropertyKey = DependencyProperty.RegisterReadOnly("RightHasMorePage", typeof(bool), typeof(Pagination), new PropertyMetadata(default(bool)));
        public static DependencyProperty RightHasMorePageProperty = RightHasMorePagePropertyKey.DependencyProperty;

        /// <summary>
        /// 应当列出的页面索引
        /// </summary>
        public Dictionary<int, bool> ListedPages
        {
            get { return (Dictionary<int, bool>)GetValue(ListedPagesProperty); }
            private set { SetValue(ListedPagesPropertyKey, value); }
        }
        private static DependencyPropertyKey ListedPagesPropertyKey = DependencyProperty.RegisterReadOnly("ListedPages", typeof(Dictionary<int, bool>), typeof(Pagination), new PropertyMetadata(default(Dictionary<int, bool>)));
        public static DependencyProperty ListedPagesProperty = ListedPagesPropertyKey.DependencyProperty;

        /// <summary>
        /// 元素的样式
        /// </summary>
        public Style ItemStyle
        {
            get { return (Style)GetValue(ItemStyleProperty); }
            set { SetValue(ItemStyleProperty, value); }
        }

        public static readonly DependencyProperty ItemStyleProperty =
            DependencyProperty.Register("ItemStyle", typeof(Style), typeof(Pagination), new PropertyMetadata(default(Style)));


        /// <summary>
        /// 在需要转到指定页面时触发
        /// </summary>
        public event RoutedEventHandler GotoPage
        {
            add { AddHandler(GotoPageEvent, value); }
            remove { RemoveHandler(GotoPageEvent, value); }
        }

        public static readonly RoutedEvent GotoPageEvent = EventManager.RegisterRoutedEvent(
        "GotoPage", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Pagination));

        protected virtual void OnGotoPage()
        {
            RoutedEventArgs args = new RoutedEventArgs();
            args.RoutedEvent = Pagination.GotoPageEvent;
            this.RaiseEvent(args);
        }

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
            if (e.Property == PageCountProperty || e.Property == CurrentPageProperty || e.Property == MaxVisiblePagesCountProperty)
            {
                this.changePage();
                if (e.Property == CurrentPageProperty)
                {
                    this.OnGotoPage();
                }
            }
        }
        private void changePage()
        {
            this.CanFirst = this.CanPrevious = (CurrentPage > 1);
            this.CanLast = this.CanNext = ((CurrentPage < PageCount));
            this.ListedPages = getListPages();
        }


        private Dictionary<int, bool> getListPages()
        {
            var cur = this.CurrentPage;
            var all = this.PageCount;
            var listcount = Math.Min(this.MaxVisiblePagesCount, all);
            if (all < 1 || listcount < 1)
            {
                return null;
            }
            var start = Math.Max(cur - Math.Max((listcount / 2), listcount - (all - cur) - 1), 1);
            var end = Math.Min(start + listcount - 1, all);
            this.LeftHasMorePage = (start > 1);
            this.RightHasMorePage = (end < all);
            Dictionary<int, bool> sp = new Dictionary<int, bool>();
            for (int i = start; i <= end; i++)
            {
                sp.Add(i, cur == i);
            }
            return sp;
        }
    }
}
